#include <sstream>
#include <fstream>
#include <map>
#include <iomanip>
#include "CTruthDataPoint.h"
#include "DataPointManager.h"

/********************************************************************/
using namespace std;
/********************************************************************/
CDataPointManager::CDataPointManager(void)
{
	m_baseName = "datapoint";
	m_path = "C:\\Users\\kscottz\\Documents\\Biometrics\\Final\\FinalProject\\data\\";
	m_fileType = ".jpg";
}
/********************************************************************/
CDataPointManager::CDataPointManager(string fname, string path)
{
	m_baseName = "datapoint";
	m_path = path;
	m_fileType = ".jpg";
	ReadFromFile(fname);
}
/********************************************************************/
CDataPointManager::CDataPointManager(std::string baseName, std::string path, std::string ext, int count, int nwidth, int startIndex)
{
	string fullName;
	CTruthDataPoint* temp=NULL;
	for( int i=startIndex; i < count+startIndex; ++i)
	{
		// really this should load data when the images is needed instead of startup, but whatever
		std::stringstream out;
		out << path << baseName << setw(nwidth) << setfill('0') << i  << ext;
		temp = new CTruthDataPoint(out.str());
		m_data.push_back(temp);
	}
}
/********************************************************************/
CDataPointManager::~CDataPointManager(void)
{
	int sz = GetSize();
	for( int i=0; i < sz; i++ )
	{
		CTruthDataPoint* temp = m_data[i];
		temp->FreeImage();
		if( temp != NULL )
		{
			delete temp;
		}
	}
	m_data.clear();
}
/********************************************************************/
CTruthDataPoint* CDataPointManager::GetDataPoint( int index )
{
	CTruthDataPoint* retVal=NULL;
	if( index < static_cast<int>(m_data.size()) )
	{
		retVal = m_data[index];
	}
	return retVal;
}
/********************************************************************/
void CDataPointManager::AddDataPoint( CTruthDataPoint* dp )
{
	if( dp != NULL )
	{
		int n = GetNextElement();
		ostringstream oss;
		oss << m_baseName << n << m_fileType;
		dp->SetOutFile(oss.str());
		m_data.push_back(dp);
	}	
}
/********************************************************************/
void CDataPointManager::AddDataPoint( IplImage* img, string inFile, double classification, CvPoint pt, CvSize sz)
{
	CTruthDataPoint* temp = NULL;
	int n = GetNextElement();
	ostringstream oss;
	oss << m_baseName << n << m_fileType;
	temp = new CTruthDataPoint(inFile,oss.str(), classification, sz, pt);
	temp->SetImage(img);
	string of = m_path+oss.str();
	cvSaveImage(of.c_str(), img);
	m_data.push_back(temp);
}
/********************************************************************/
int CDataPointManager::GetSize(void)
{
	return static_cast<int>(m_data.size());
}
/********************************************************************/
int CDataPointManager::GetNextElement(void)
{
	return( GetSize() );
}
/********************************************************************/
bool CDataPointManager::WriteToFile( string fname )
{
	string realFName = m_path+fname;
	ofstream ofs;
	int count = -1;
	ofs.open(realFName.c_str());

	if( ofs.is_open() && ofs.good() )
	{
		int sz = GetSize();
		ofs << sz << endl;
		for( int i=0; i < sz;i++)
		{
			ofs << m_data[i]->PrintToLine();
			ofs << endl;
			count++;
		}
	}
	ofs.close();
	return( count >= 0 );
			
}
/********************************************************************/
bool CDataPointManager::ReadFromFile( string fname )
{
	bool retVal = false;
	string realFName = m_path+fname;
	ifstream ifs;
	ifs.open(realFName.c_str());
	string infile;
	string outfile;
	double classification;
	int x=0,y=0,w=0,h=0;
	int sz=0;
	if( ifs.is_open() )
	{
		ifs >> sz;
		for( int i=0; i < sz && ifs.good();i++)
		{
			ifs >> infile;
			ifs >> outfile;
			ifs >> classification;
			ifs >> x >> y >> w >> h;
			CTruthDataPoint* temp=NULL;
			temp = new CTruthDataPoint(infile,outfile,classification, cvSize(w,h), cvPoint(x,y));
			m_data.push_back(temp);
		}
		if( ifs.good() )
			retVal = true;
		ifs.close();
	}
	return retVal; 
}
/********************************************************************/
vector<string> CDataPointManager::GetCurrentFiles(void)
{
	map<string,int> names;
	int sz = GetSize();
	for( int i=0; i<sz; i++ )
	{
		names[m_data[i]->GetInFile()]++;
	}
	map<string,int>::iterator iter;
	vector<string> retVal;
	for( iter = names.begin(); iter != names.end(); ++iter )
	{
		retVal.push_back(iter->first);
	}
	return(retVal);
}
/********************************************************************/
void CDataPointManager::SetBaseName( string baseName )
{
	m_baseName = baseName;
}
/********************************************************************/
string CDataPointManager::GetBaseName( void )
{
	return m_baseName;
}
/********************************************************************/
double CDataPointManager::GetClassificationError(void)
{
	int sz = GetSize(); 
	int count = 0;
	for( int i=0; i< sz; i++ )
	{
		if( m_data[i]->GetClassification().IsIncorrect())
		{
			count++;
		}
	}
	return( static_cast<double>(count)/static_cast<double>(sz)); 
}
/********************************************************************/
void CDataPointManager::SetClassificationTruth( double truth_label )
{
	int sz = GetSize();
	for( int i=0; i<sz; i++ )
	{
		m_data[i]->GetClassification().SetTruth(truth_label);
	}
}
/********************************************************************/
void CDataPointManager::SetFileType( string fType )
{
	m_fileType = fType;
}
/********************************************************************/
string CDataPointManager::GetFileType(void)
{
	return m_fileType; 
}
/********************************************************************/ 
int CDataPointManager::LoadAllImages(void)
{
	int sz = GetSize();
	int retVal = 0;
	for( int i=0; i < sz; i++ )
	{
		if( m_data[i]->LoadSourceImage() )
			retVal++;
	}
	return retVal;
}
/********************************************************************/
bool CDataPointManager::SaveAllImages(void)
{
	int sz = GetSize();
	bool retVal = true;
	for( int i=0; i < sz; i++ )
	{
		if( !m_data[i]->SaveImage() )
			retVal = false;
	}
	return retVal;
}
/********************************************************************/